package com.maxd.service.member;

import com.google.common.collect.Lists;
import com.maxd.adapter.LoginUserHolder;
import com.maxd.bean.PageRes;
import com.maxd.bean.activity.ActivityJoinData;
import com.maxd.bean.activity.JoinActivityReq;
import com.maxd.bean.member.JoinMemberReq;
import com.maxd.constants.PayScene;
import com.maxd.error.DescribeException;
import com.maxd.error.ExceptionEnum;
import com.maxd.model.*;
import com.maxd.respository.MemberInfoRepository;
import com.maxd.respository.UserMemberRecordRepository;
import com.maxd.respository.activitties.ActivityJoinRecordRepository;
import com.maxd.respository.activitties.RwActivityRepository;
import com.maxd.service.pay.IPayRecordService;
import com.maxd.utils.AssertUtil;
import com.maxd.utils.JsonUtils;
import com.maxd.utils.PageUtils;
import com.maxd.utils.SeqUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.*;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.persistence.criteria.Predicate;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class MemberService implements IMemberService {

    private static final Logger log = LoggerFactory.getLogger(MemberService.class);
    @Autowired
    private MemberInfoRepository memberInfoRepository;

    @Autowired
    private UserMemberRecordRepository userMemberRecordRepository;

    @Autowired
    private IPayRecordService payRecordService;

    @Override
    public void save(MemberInfo memberInfo) {
        // 参数校验，暂时不做
        if(memberInfo.getId() == null) {
            // 新增会员
            memberInfo.setCreateBy(LoginUserHolder.getAdminId());
            memberInfo.setUpdateBy(LoginUserHolder.getAdminId());
        } else {
            memberInfo.setUpdateBy(LoginUserHolder.getAdminId());
            memberInfo.setUpdateTime(new Date());
        }
        memberInfoRepository.save(memberInfo);
    }

    @Override
    public List<MemberInfo> list() {
        return memberInfoRepository.findAll(Sort.by(Sort.Direction.DESC,"updateTime"));
    }

    @Override
    public UserMemberRecord joinMember(JoinMemberReq req) {
        log.info("购买会员入参:{}", JsonUtils.toJsonString(req));
        // 登录校验
        Long userId = LoginUserHolder.getUserId();
        AssertUtil.assertTrue(userId != null && userId > 0, ExceptionEnum.WRONT_TOKEN);
        // 查询活动信息
        MemberInfo memberInfo = memberInfoRepository.findById(req.getMemberId()).orElse(null);
        log.info("查询到会员信息:{}", JsonUtils.toJsonString(memberInfo));
        AssertUtil.notNull(memberInfo, ExceptionEnum.MEMBER_NOF);
        AssertUtil.assertTrue("1".equals(memberInfo.getStatus()), ExceptionEnum.MEMBER_NOT_EFFECT);
        // 金额是否匹配，暂不考虑优惠券、积分抵扣的情况
        AssertUtil.assertTrue(memberInfo.getPrice().compareTo(req.getAmount()) == 0, ExceptionEnum.PAY_MONEY_ERROR);
        UserMemberRecord record = buildUserMemberRec(req, memberInfo);
        if(req.getAmount().compareTo(BigDecimal.ZERO) > 0) {
            // 需要支付
            PayRecord payRecord = payRecordService.savePayRecord(record.getTransId(), req.getAmount(), record.getMemberName(), PayScene.MEMBER_PAY);
            record.setPaySeq(payRecord.getPaySeq());
        }
        userMemberRecordRepository.save(record);
        return record;
    }

    @Override
    public PageRes<UserMemberRecord> userMemberInfo(Integer pageNo, Integer pageSize, Long userId, Long memberId, String status) {

        // 分页参数
        Sort sort = Sort.by(Sort.Direction.DESC, "createTime");
        Pageable pageable = PageRequest.of(pageNo, pageSize, sort);

        Specification<UserMemberRecord> queryCondition = (root, query, criteriaBuilder) -> {
            List<Predicate> predicates = Lists.newArrayList();
            if(userId != null) {
                predicates.add(criteriaBuilder.equal(root.get("userId"), userId));
            }
            if(memberId != null) {
                predicates.add(criteriaBuilder.equal(root.get("memberId"), memberId));
            }
            if(StringUtils.isNotEmpty(status)) {
                predicates.add(criteriaBuilder.equal(root.get("status"), status));
            }
            return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
        };
        Page<UserMemberRecord> pageList = userMemberRecordRepository.findAll(queryCondition, pageable);
        log.info("查询到用户的会员信息为:{}", JsonUtils.toJsonString(pageList));

        return new PageRes<>(pageList.getTotalElements(), pageList.getContent());
    }

    @Override
    public void cancel(String transId, Long userId) {
        UserMemberRecord record = findByTransId(transId);
        if(record == null || !record.getUserId().equals(userId)) {
            throw new DescribeException(ExceptionEnum.MEMBER_BUY_NOF);
        }
        if("3".equals(record.getStatus())) {
            log.info("会员购买已经被取消,无需重复处理.");
            return;
        }
        if("2".equals(record.getStatus())) {
            log.info("会员购买已经支付成功,不允许取消.");
            throw new DescribeException(ExceptionEnum.DATA_CHANGED);
        }
        // 更新记录状态
        userMemberRecordRepository.updateStatus(transId, "3");
    }

    public UserMemberRecord findByTransId(String transId) {
        UserMemberRecord param = new UserMemberRecord();
        param.setTransId(transId);
        return userMemberRecordRepository.findOne(Example.of(param)).orElse(null);
    }

    private UserMemberRecord buildUserMemberRec(JoinMemberReq req, MemberInfo memberInfo) {
        UserMemberRecord record = new UserMemberRecord();
        record.setTransId(SeqUtils.dateSeq());
        record.setUserId(LoginUserHolder.getUserId());
        record.setMemberId(memberInfo.getId());
        record.setMemberName(memberInfo.getMemberName());
        record.setAmount(req.getAmount());
        record.setPrice(memberInfo.getPrice());
        record.setStatus("0");
        record.setCreateBy(String.valueOf(record.getUserId()));
        record.setUpdateBy(String.valueOf(record.getUserId()));
        return record;
    }
}
